package com.tanhua.server.interceptor;

import cn.hutool.http.HttpRequest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.common.utils.Cache;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.client.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @Auther: you
 * @Date: 2021/05/30/19:06
 * @Description:
 */
//Interceptor拦截器
@Component
public class RedisCacheInterceptor implements HandlerInterceptor {
    @Value("${tanhua.cache.enable}")
    private Boolean enable;

    @Autowired
    private RedisTemplate<String, String>  redisTemplate;

    private static final ObjectMapper MAPPER = new ObjectMapper();


//    preHandle：在业务处理器处理请求之前被调用。预处理，可以进行编码、安全控制、权限校验等处理；
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //是否开启全局通用缓存开关
        if (!enable){
            return true; //放行
        }

        //import cn.hutool.http.HttpRequest;
        HttpRequest httpRequest = HttpRequest.get("www.baidu.com");




        //校验handler是否是HandlerMethod（"控制器方法"则通过HandlerMethod来包装和表示）
        if (!(handler instanceof HandlerMethod)){
            return true;
        }

        //判断是否是get请求
        if(!(((HandlerMethod)handler).hasMethodAnnotation(GetMapping.class))){
            return true;
        }

        //判断是否添加了@Cache注解(被@Cache修饰的get请求需要被拦截)
        if(!(((HandlerMethod) handler).hasMethodAnnotation(Cache.class))) {
            return true;
        }

        String redisKey=createRedisKey(request);
        //未命中
        if (!(redisTemplate.hasKey(redisKey))){
            return true;
        }

        //命中，直接返回缓存中数据，不在访问controller控制器
        String cacheData = redisTemplate.opsForValue().get(redisKey);
        // 将data数据进行响应
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().write(cacheData);

        return false;
    }

   public static String createRedisKey(HttpServletRequest request) throws JsonProcessingException {

        String url = request.getRequestURI();

        //TODO 打印请求路径的区别
        System.out.println("URI:"+url);
        System.out.println("URL:"+request.getRequestURL());
        System.out.println("ContextPath:"+request.getContextPath());
        System.out.println("ServletPath:"+request.getServletPath());

        Map<String, String[]> parameterMap = request.getParameterMap();
        String param = MAPPER.writeValueAsString(parameterMap);


        System.out.println("map:"+parameterMap);
        System.out.println("param:"+param);

        String token = request.getHeader("Authorization");
        String data=url+"_"+param+"_"+token;
        //md5加密
        return "SERVER_CACHE_DATA_" + DigestUtils.md5Hex(data);


    }

    //    postHandle：在业务处理器处理请求执行完成后，生成视图之前执行。后处理（调用了Service并返回ModelAndView，但未进行页面渲染），有机会修改ModelAndView （这个博主就基本不怎么用了）；
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

//    afterCompletion：在DispatcherServlet完全处理完请求后被调用，可用于清理资源等。返回处理（已经渲染了页面）；
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
